#pragma once
#include "IEntityMgr.h"
#include "MarkerEntity.h"
#include "Scene.h"
#include "Cache.h"
#include "Global.h"

class MarkerMgr : protected IEntityMgr {
public:
	static MarkerMgr* get() {
		static auto instance = new MarkerMgr;
		return instance;
	}

	void update(MarkerType type) {
		switch(type) {
			case MarkerType::ALC: updateALC(); break;
			case MarkerType::SQ_ALC: updateSQ_ALC(); break;
			case MarkerType::LDW: updateLDW(); break;
			case MarkerType::DCLC: updateDCLC(); break;
			case MarkerType::ACC_TG: updateAccTG(); break;
			case MarkerType::TailLamp: updateTailLamp(); break;
			case MarkerType::RoadBg: updateRoadBg(); break;
			case MarkerType::ZhicheCircle: updateZhicheCircle(); break;
			default: break;
		}
	}

	void updateModelAccFD(int modelID) {
		removeModelAccFD(modelID);
		addModelAccFD(modelID);
	}

	void removeModelAccFD(int modelID) {
		Scene::remove(m_modelAccFDMap.take(modelID));
	}

	void remove(MarkerType type) {
		Scene::remove(m_markerMap.take(type));
	}

	void updateEntities() override {}// do nothing

	void clear() override {
		auto allMarkerTypes = m_markerMap.keys();
		auto allAccFDModelIDs = m_modelAccFDMap.keys();
		for (MarkerType type : allMarkerTypes)
			remove(type);
		for (int ID : allAccFDModelIDs)
			removeModelAccFD(ID);
	}

private:
	MarkerMgr() = default;

	void updateALC() {
		remove(MarkerType::ALC);
		if (!Cache::isALCReady())
			return;
		if (Global::isBlinkShowing())
			addMarker(MarkerType::ALC);
	}

	void updateLDW() {
		remove(MarkerType::LDW);
		if (!Cache::isLDWReady())
			return;
		if (Global::isBlinkShowing())
			addMarker(MarkerType::LDW);
	}

	void updateAccTG() {
		remove(MarkerType::ACC_TG);
		ACC_TG accTG = Cache::status().accTG;
		if (Enum_isInvalidOrOff(accTG))
			return;
		addMarker(MarkerType::ACC_TG);
	}

	void updateTailLamp() {
		remove(MarkerType::TailLamp);
		TailLamp lamp = Cache::status().tailLamp;
		if (Enum_isInvalidOrOff(lamp))
			return;
		addMarker(MarkerType::TailLamp);
	}

	void updateDCLC() {
		remove(MarkerType::DCLC);
		if (!Cache::isDCLCReady())
			return;
		addMarker(MarkerType::DCLC);
	}

	void updateSQ_ALC() {
		remove(MarkerType::SQ_ALC);
		if (!Cache::isSQ_ALCReady())
			return;
		addMarker(MarkerType::SQ_ALC);
	}

	void updateRoadBg() {
		remove(MarkerType::RoadBg);
		if (Cache::validLineNum() < 2)
			return;
		addMarker(MarkerType::RoadBg);
	}

	void updateZhicheCircle() {
		remove(MarkerType::ZhicheCircle);
		addMarker(MarkerType::ZhicheCircle);
	}

	void addMarker(MarkerType type) {
		auto entity = new MarkerEntity(type);
		m_markerMap.insert(type, entity);
		Scene::add(entity);
	}

	void addModelAccFD(int modelID) {
		const auto& model = Cache::modelArg(modelID);
		if (!model.isAccTracking || !model.color.isValid())// color also should be set!
			return;
		auto entity = new MarkerEntity(MarkerType::ACC_FD, modelID);
		m_modelAccFDMap.insert(modelID, entity);
		Scene::add(entity);
	}

	CMap<MarkerType, MarkerEntity*> m_markerMap;
	CMap<int, MarkerEntity*> m_modelAccFDMap;
};